#pragma once
#include "DJoint.h"

namespace Skill
{
	namespace Ode
	{
		ref class DWorld;
		ref class DVector3;
		namespace Joints
		{
			ref class DJointGroup;
			public ref class DPrismaticUniversal : DJoint
			{
			protected:
				virtual void CollectManagedMemory() override;
			public:

				///<summary>
				/// Create a new joint of the PU (Prismatic and Universal) type.
				///</summary>
				///<param name = "world"> Wrold </param>
				///<param name = "group">
				/// set to null to allocate the joint normally.
				/// If it is valid the joint is allocated in the given joint group.
				///</param>				
				DPrismaticUniversal(DWorld^ world , DJointGroup^ group);




				///<summary>
				/// Gets or set the joint anchor point, in world coordinates.
				///</summary>
				///<returns>
				/// the point on body 1. If the joint is perfectly satisfied,
				/// this will be the same as the point on body 2.			
				///</returns>
				REF_PROP_DECLARATION_GETSET(DVector3,Anchor);

				///<summary>
				/// Set anchor
				///</summary>
				void SetAnchorDelta(dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz);

				///<summary>
				/// Set anchor
				///</summary>
				void SetAnchorDelta(DVector3^ p, DVector3^ d);

				///<summary>
				/// Gets or set the axis for the first axis or the universal articulation
				///</summary>
				REF_PROP_DECLARATION_GETSET(DVector3,Axis1);

				///<summary>
				/// Gets or set the axis for the second axis or the universal articulation
				///</summary>
				REF_PROP_DECLARATION_GETSET(DVector3,Axis2);

				///<summary>
				/// Gets or set the axis for the prismatic articulation
				///</summary>
				REF_PROP_DECLARATION_GETSET(DVector3,Axis3);

				///<summary>
				/// set the axis for the prismatic articulation				
				/// This function was added for convenience it is the same as				
				///</summary>
				VALUE_PROP_DECLARATION_GETSET(DVector3^,AxisP);

				///<summary>
				/// parameterX where X equal 2 refer to parameter for second axis of the
				///       universal articulation
				/// parameterX where X equal 3 refer to parameter for prismatic
				///       articulation
				///</summary>


				///<summary>
				/// set joint parameter
				///</summary>
				void SetParam(DJointParameters parameter, dReal value);	

				///<summary>
				/// Get joint parameter
				///</summary>
				dReal GetParam(DJointParameters parameter);

				///<summary>
				/// Applies the torque about the rotoide axis of the PU joint
				///
				/// That is, it applies a torque with specified magnitude in the direction
				/// of the rotoide axis, to body 1, and with the same magnitude but in opposite
				/// direction to body 2. This function is just a wrapper for dBodyAddTorque()}
				///</summary>
				//void AddTorque(dReal torque);


				///<summary>
				/// Get the PU linear position (i.e. the prismatic's extension)
				///
				/// When the axis is set, the current position of the attached bodies is
				/// examined and that position will be the zero position.
				///
				/// The position is the "oriented" length between the
				/// position = (Prismatic axis) dot_product [(body1 + offset) - (body2 + anchor2)]
				///</summary>
				VALUE_PROP_DECLARATION_GET(dReal,Position);

				///<summary>
				/// Get the PR linear position's time derivative				
				///</summary>
				VALUE_PROP_DECLARATION_GET(dReal,PositionRate);				




				///<summary>
				/// Get both angles at the same time.
				/// This function combine Angle1 and Angle2 together
				/// and try to avoid redundant calculation
				///</summary>				
				///<param name = "angle1"> The angle between the body1 and the axis 1 </param>
				///<param name = "angle2"> The angle between the body2 and the axis 2 </param>										
				void GetAngles([OutAttribute]dReal %angle1, [OutAttribute]dReal %angle2);

				///<summary>
				/// Get angle
				///</summary>
				VALUE_PROP_DECLARATION_GET(dReal,Angle1);

				///<summary>
				/// Get time derivative of angle1
				///</summary>
				VALUE_PROP_DECLARATION_GET(dReal,Angle1Rate);


				///<summary>
				/// Get angle
				///</summary>
				VALUE_PROP_DECLARATION_GET(dReal,Angle2);

				///<summary>
				/// Get time derivative of angle2
				///</summary>
				VALUE_PROP_DECLARATION_GET(dReal,Angle2Rate);				
			};
		}
	}
}